package cn.jinbyte.web.filter;

import cn.jinbyte.web.config.CorsProperties;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.List;

/**
 * CORS跨域过滤器
 * <p>
 *     基于配置文件参数对请求进行过滤
 * </p>
 * @author jinty
 */
public class CorsFilter implements Filter {

    private final CorsProperties corsProperties;

    public CorsFilter(CorsProperties corsProperties) {
        this.corsProperties = corsProperties;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        // 如果CORS未启用，直接放行
        if (!corsProperties.isEnabled()) {
            chain.doFilter(request, response);
            return;
        }

        // 设置允许的源
        List<String> allowedOrigins = corsProperties.getAllowedOrigins();
        String origin = httpRequest.getHeader("Origin");
        if (origin != null && !allowedOrigins.isEmpty()) {
            if (allowedOrigins.contains("*")) {
                httpResponse.setHeader("Access-Control-Allow-Origin", origin);
            } else if (allowedOrigins.contains(origin)) {
                httpResponse.setHeader("Access-Control-Allow-Origin", origin);
            }
        }

        // 设置允许的凭证
        if (corsProperties.isAllowCredentials()) {
            httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
        }

        // 设置允许的方法
        String allowedMethods = String.join(",", corsProperties.getAllowedMethods());
        httpResponse.setHeader("Access-Control-Allow-Methods", allowedMethods);

        // 设置允许的请求头
        String allowedHeaders = String.join(",", corsProperties.getAllowedHeaders());
        httpResponse.setHeader("Access-Control-Allow-Headers", allowedHeaders);

        // 设置暴露的响应头
        if (!corsProperties.getExposedHeaders().isEmpty()) {
            String exposedHeaders = String.join(",", corsProperties.getExposedHeaders());
            httpResponse.setHeader("Access-Control-Expose-Headers", exposedHeaders);
        }

        // 设置预检请求的缓存时间
        httpResponse.setHeader("Access-Control-Max-Age", String.valueOf(corsProperties.getMaxAge()));

        // 处理预检请求
        if ("OPTIONS".equalsIgnoreCase(httpRequest.getMethod())) {
            httpResponse.setStatus(HttpServletResponse.SC_OK);
            return;
        }

        chain.doFilter(request, response);
    }
}
